#pragma once
#include "net.hpp"
#include "message.hpp"

namespace myrpc 
{
    // 丐版
    // class Dispatcher    // 调度器
    // {
    // public:
    //     using ptr = std::shared_ptr<Dispatcher>;
    //     // 注册消息类型 回调函数
    //     void registerHandler(MType mtype, const MessageCallback &handler) 
    //     {
    //         std::unique_lock<std::mutex> lock(_mutex);
    //         _handlers.insert(std::make_pair(mtype, handler));
    //     }
    //     // 回调函数
    //     void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) 
    //     {
    //         // 找到消息类型对应的业务处理函数，进行调用即可
    //         std::unique_lock<std::mutex> lock(_mutex);
    //         auto it = _handlers.find(msg->mtype());
    //         if (it != _handlers.end()) 
    //         {
    //             return it->second(conn, msg);
    //         }
    //         // 没有找到指定类型的处理回调--因为客户端和服务端都是我们自己设计的，因此不可能出现这种情况
    //         ELOG("收到未知类型的消息: %d！", msg->mtype());
    //         conn->shutdown();
    //     }
    // private:
    //     std::mutex _mutex;
    //     std::unordered_map<MType, MessageCallback> _handlers;
    // };

    // 高配版
    // Callback 专门用来存储hanlder
    class Callback 
    {
    public:
        using ptr = std::shared_ptr<Callback>;
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
    };

    // 模板类 继承于 Callback
    template<typename T>
    class CallbackT : public Callback
    {
    public:
        using ptr = std::shared_ptr<CallbackT<T>>;
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;

        CallbackT(const MessageCallback &handler)
            :_handler(handler) 
        { }
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override 
        {
            auto type_msg = std::dynamic_pointer_cast<T>(msg);
            _handler(conn, type_msg);
        }
    private:
        MessageCallback _handler;
    };

    class Dispatcher    // 调度器
    {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        template<typename T>
        // 注册消息类型 回调函数
        // const typename CallbackT<T>::MessageCallback &handler 设为模板函数，方便接收不同类型的消息
        void registerHandler(MType mtype, const typename CallbackT<T>::MessageCallback &handler) 
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto cb = std::make_shared<CallbackT<T>>(handler);
            _handlers.insert(std::make_pair(mtype, cb));
        }
        // 回调函数
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) 
        {
            // 找到消息类型对应的业务处理函数，进行调用即可
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _handlers.find(msg->mtype());
            if (it != _handlers.end()) 
            {
                // 父类指针指向虚函数->构成多态
                return it->second->onMessage(conn, msg);
            }
            // 没有找到指定类型的处理回调--因为客户端和服务端都是我们自己设计的，因此不可能出现这种情况
            ELOG("收到未知类型的消息: %d！", msg->mtype());
            conn->shutdown();
        }
    private:
        std::mutex _mutex;
        std::unordered_map<MType, Callback::ptr> _handlers;
    };
}